/**
 * Model.java 2008-05-29
 * 
 * Linker is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <http://www.gnu.org/licenses/>.
 *
 */

package linker.list;

import java.io.FileNotFoundException;
import java.io.IOException;

import javax.swing.JList;
import javax.swing.ListSelectionModel;

import org.jivesoftware.smack.PacketListener;
import org.jivesoftware.smack.Roster;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.Roster.SubscriptionMode;
import org.jivesoftware.smack.filter.PacketFilter;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.packet.Presence;

import linker.Settings;
import linker.buddy.BuddyList;
import linker.gui.ListMouseListener;
import linker.gui.MainWindow;
import linker.message.MessageItem;
import linker.message.MessageList;
import linker.plugin.PluginList;
import linker.status.StatusManager;

/**
 * The view list of mainWindow.
 * 
 * @version 2008-05-29
 * @author Jianfeng tujf.cn@gmail.com
 * 
 */

public class ViewList extends JList {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	/**
	 * The list's action.
	 */
	private ListAction listAction;

	/**
	 * The singleton refer to buddylist.
	 */
	private static BuddyList buddyList;

	/**
	 * The singleton refer to messagelist.
	 */
	private static MessageList messageList;

	/**
	 * The singleton refer to pluginList.
	 */
	private static PluginList pluginList;

	/**
	 * 
	 * @param connection
	 *            The connected XMPPConnection.
	 */
	public ViewList(final XMPPConnection connection) {
		super();

		// Get lists
		MainWindow mainWindow = new MainWindow(ViewList.this);
		StatusManager.getManager(mainWindow);
		String status = Settings.getSettings().getValue("status");
		StatusManager.getManager(null).setStatus(null, status);

		// messageList.
		messageList = new MessageList(mainWindow);

		// File buddylist and create message list
		buddyList = new BuddyList(connection);

		// Inistail buddylist by roster;
		Roster roster = connection.getRoster();
		roster.setSubscriptionMode(SubscriptionMode.manual);
		buddyList.initialByRoster(connection.getRoster());
		buddyList.refilter(null);

		// create functionList
		try {
			pluginList = new PluginList();
			pluginList.loadPlugins();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

		/**
		 * Add packetListener and display every packet information
		 */
		connection.addPacketListener(new PacketListener() {
			public void processPacket(final Packet packet) {

				// Display packet information for debug
				System.out.println(packet.toXML());

				// Judge the kind of packet
				if (packet instanceof Presence) {
					// is a presence
					Presence presence = (Presence) packet;
					buddyList.setPresence(presence);
				} else if (packet instanceof Message) {
					// is a message
					Message message = (Message) packet;

					// Skip error message.
					if (message.getType() == Message.Type.error) {
						return;
					}

					buddyList.processMessage(message);

				} else {
					// is a ID
					System.out.println("Undo packtype:" + packet.getXmlns());
				}
			}
		}, new PacketFilter() {
			// Accept all
			public boolean accept(final Packet packet) {
				return true;
			}
		});

		// Set
		setModel(buddyList);
		setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		setCellRenderer(new CellRender());

		// Set list action.
		listAction = new ListAction(buddyList);
		addMouseListener(new ListMouseListener(listAction, this));

		// Display the mainWindow after the initial is done.
		mainWindow.setVisible(true);
	}

	/**
	 * Add element to the current list by a given string.
	 * 
	 * @param add
	 *            The given string.
	 */
	public final void addElement(final String add) {
		if (((Listmodel) getModel()).getSize() == 0) {
			((Listmodel) getModel()).addElement(add);
		}
	}

	/**
	 * The names of List.
	 * 
	 */
	public static enum LISTNAME {
		/**
		 * 
		 */
		BUDDYLIST, MESSAGELIST, PLUGINLIST
	}

	/**
	 * Change the current list Model by there name.
	 * 
	 * @param name
	 *            The list's name.
	 */
	public final void setListModelByName(final LISTNAME name) {
		// System.out.println("Change list model");

		if (name == LISTNAME.MESSAGELIST) {
			setModel(messageList);
			listAction.setState(messageList);
		} else if (name == LISTNAME.BUDDYLIST) {
			setModel(buddyList);
			listAction.setState(buddyList);
		} else if (name == LISTNAME.PLUGINLIST) {
			setModel(pluginList);
			listAction.setState(pluginList);
		}
	}

	/**
	 * Change list.
	 * 
	 */
	public final void changeList() {
		if (getModel() == buddyList) {
			setModel(messageList);
			listAction.setState(messageList);
		} else if (getModel() == messageList) {
			setModel(pluginList);
			listAction.setState(pluginList);
		} else {
			setModel(buddyList);
			listAction.setState(buddyList);
		}
	}

	/**
	 * 
	 * @param newMessage
	 *            The messageItem to be added.
	 */
	public static void addMessage(final MessageItem newMessage) {
		messageList.addMessage(newMessage);
	}

	/**
	 * Get buddy list.
	 * 
	 * @return buddyList
	 */
	public static BuddyList getBuddyList() {
		return buddyList;
	}

	/**
	 * Remove message from messagelist.
	 * 
	 * @param message
	 *            The message to be removed.
	 */
	public static void removeMessage(final MessageItem message) {
		messageList.removeMessage(message);
	}

	/**
	 * Get message list.
	 * 
	 * @return The messagelist's refer.
	 */
	public static MessageList getMessageList() {
		return messageList;
	}

	/**
	 * Get plugin list.
	 * 
	 * @return The pluginList's refer.
	 */
	public static PluginList getPluginList() {
		return pluginList;
	}

	/**
	 * Set the online only to buddylist.
	 * 
	 * @param b
	 *            The new value.
	 */
	public final void setOnlineOnly(final boolean b) {
		buddyList.setOnlineOnly(b);
	}

}
